package com.dlc.shop.groupbuy.api.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.dlc.shop.bean.app.dto.*;
import com.dlc.shop.bean.enums.DeliveryType;
import com.dlc.shop.bean.enums.DvyType;
import com.dlc.shop.bean.enums.OrderType;
import com.dlc.shop.bean.model.Order;
import com.dlc.shop.bean.model.UserAddr;
import com.dlc.shop.bean.vo.UserDeliveryInfoVO;
import com.dlc.shop.common.constants.SegmentIdKey;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.i18n.I18nMessage;
import com.dlc.shop.common.response.ResponseEnum;
import com.dlc.shop.common.response.ServerResponseEntity;
import com.dlc.shop.common.util.BeanUtil;
import com.dlc.shop.delivery.api.manager.DeliveryOrderManager;
import com.dlc.shop.delivery.api.manager.StationOrderManager;
import com.dlc.shop.groupbuy.common.api.dto.ApiGroupActivityDto;
import com.dlc.shop.groupbuy.common.api.dto.ApiGroupSkuDto;
import com.dlc.shop.groupbuy.common.api.param.ApiGroupOrderSubmitParam;
import com.dlc.shop.groupbuy.common.api.param.GroupOrderParam;
import com.dlc.shop.groupbuy.common.bo.GroupOrderBO;
import com.dlc.shop.groupbuy.common.enums.ActivityStatusEnum;
import com.dlc.shop.groupbuy.common.enums.TeamStatusEnum;
import com.dlc.shop.groupbuy.common.model.GroupTeam;
import com.dlc.shop.groupbuy.common.service.GroupActivityService;
import com.dlc.shop.groupbuy.common.service.GroupOrderService;
import com.dlc.shop.groupbuy.common.service.GroupTeamService;
import com.dlc.shop.manager.SubmitOrderManager;
import com.dlc.shop.manager.UserLevelOrderManager;
import com.dlc.shop.manager.impl.ConfirmOrderManager;
import com.dlc.shop.manager.impl.ShopCartAdapter;
import com.dlc.shop.manager.impl.ShopCartItemAdapter;
import com.dlc.shop.security.api.util.SecurityUtils;
import com.dlc.shop.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @author Yami
 */
@RestController
@RequestMapping("/p/group/order")
@Tag(name = "拼团订单接口")
@AllArgsConstructor
public class GroupOrderController {

    private final GroupTeamService groupTeamService;
    private final GroupOrderService groupOrderService;
    private final SegmentService segmentService;
    private final SubmitOrderManager submitOrderManager;
    private final GroupActivityService groupActivityService;
    private final SkuService skuService;
    private final ProductService productService;
    private final ConfirmOrderManager confirmOrderManager;
    private final ShopCartAdapter shopCartAdapter;
    private final ShopCartItemAdapter shopCartItemAdapter;
    private final DeliveryOrderManager deliveryOrderManager;
    private final ShopCustomerService shopCustomerService;
    private final UserAddrService userAddrService;
    private UserLevelOrderManager userLevelOrderManager;
    private StationOrderManager stationOrderManager;
    private final FlowLogService flowLogService;


    @PostMapping("/confirm")
    @Operation(summary = "结算，生成团购订单信息" , description = "传入参团/开团所需要的参数进行下单,如果用户为开团时拼团团队Id(groupTeamId)为0,如用户为参团则需要将拼团团队Id(groupTeamId)需要带上")
    public ServerResponseEntity<ShopCartOrderMergerDto> confirm(@Valid @RequestBody GroupOrderParam groupOrderParam) {
        //pc端 立即购买
        if(Objects.isNull(groupOrderParam.getDvyTypes()) && Objects.nonNull(groupOrderParam.getOrderItem())){
            groupOrderParam.setDvyTypes(Collections.singletonList(new DvyTypeDTO(groupOrderParam.getOrderItem().getShopId(), DvyType.DELIVERY.value())));
        }
        String userId = SecurityUtils.getUser().getUserId();
        ApiGroupSkuDto apiGroupSku = checkActivityAndGetGroupSku(groupOrderParam);
        List<ShopCartItemDto> shopCartItemsDb = shopCartItemAdapter.getActivityShopCartItem(groupOrderParam.getOrderItem(), groupOrderParam.getDvyTypes(), apiGroupSku.getActPrice(), userId, null);
        // 将要返回给前端的完整的订单信息
        ShopCartOrderMergerDto shopCartOrderMerger = new ShopCartOrderMergerDto();
        shopCartOrderMerger.setDvyTypes(groupOrderParam.getDvyTypes());
        shopCartOrderMerger.setOrderType(OrderType.GROUP);
        shopCartOrderMerger.setUserId(userId);

        // 获取用户地址信息
        UserDeliveryInfoVO userDeliveryInfo = confirmOrderManager.getUserDeliveryInfoVO(shopCartItemsDb, userId, groupOrderParam.getDvyTypes(), groupOrderParam.getAddrId());

        // 筛选过滤掉不同配送的商品
        List<ShopCartItemDto> shopCartItems = confirmOrderManager.filterShopItemsByType(shopCartOrderMerger, userDeliveryInfo, shopCartItemsDb);
        // 该商品不满足任何的配送方式
        if (CollectionUtil.isEmpty(shopCartItems)) {
            //订单的地址信息
            UserAddr userAddr = userAddrService.getUserAddrByUserId(groupOrderParam.getAddrId(), userId);
            shopCartOrderMerger.setUserAddr(BeanUtil.map(userAddr, UserAddrDto.class));
            shopCartOrderMerger.setShopCartOrders(new ArrayList<>());
            return ServerResponseEntity.success(shopCartOrderMerger);
        }

        // 自提订单处理
        stationOrderManager.handleStationOrder(shopCartOrderMerger, shopCartItems, userDeliveryInfo);

        ShopCartItemDto firstShopCartItem = shopCartItems.get(0);
        // 商品类别 0.实物商品 1. 虚拟商品 2.组合商品
        int mold = 0;
        if (shopCartItems.stream().filter(shopCartItemDto -> shopCartItemDto.getMold() == 1).count() == shopCartItems.size()) {
            // 订单项中的所有商品都为虚拟商品时，才是虚拟订单
            mold = 1;
            shopCartOrderMerger.getDvyTypes().forEach(s->s.setDvyType(DeliveryType.NO_EXPRESS.getValue()));
        }
        shopCartOrderMerger.setMold(mold);
        // 是否为预售订单
        groupOrderParam.setPreSellStatus(firstShopCartItem.getPreSellStatus());
        shopCartOrderMerger.setPreSellStatus(firstShopCartItem.getPreSellStatus());

        // 购物车
        List<ShopCartDto> shopCarts = shopCartAdapter.getShopCarts(shopCartItems);

        // 计算运费，获取用户地址，自提信息
        if (Objects.equals(mold, 0)) {
            userDeliveryInfo = deliveryOrderManager.calculateAndGetDeliverInfo(shopCartItems, userDeliveryInfo);
        }

        // 当算完一遍店铺的各种满减活动时，重算一遍订单金额
        confirmOrderManager.recalculateAmountWhenFinishingCalculateShop(shopCartOrderMerger, shopCarts, userDeliveryInfo);

        // 等活动处理完之后，再插入sku的库存区域id -- 赠品、套餐和组合商品需要在marketing模块中处理
        confirmOrderManager.handleShopCartStockPoint(userDeliveryInfo, shopCarts, shopCartItemsDb, shopCartOrderMerger.getMold());

        // 店铺会员等级优惠计算（主要计算包邮，活动订单不计算折扣）
        if (userLevelOrderManager != null) {
            userLevelOrderManager.calShopLevelDiscount(shopCartOrderMerger);
        }
        confirmOrderManager.reCalAmountWhenFinishCalShop(shopCartOrderMerger);
        // 平台等级折扣计算（主要计算包邮，活动订单不计算折扣）
        if (userLevelOrderManager != null) {
            userLevelOrderManager.calculateLevelDiscount(shopCartOrderMerger);
        }
        // 结束平台优惠的计算之后，还要重算一遍金额
        confirmOrderManager.recalculateAmountWhenFinishingCalculatePlatform(shopCartOrderMerger);

        // 计算平台佣金
        confirmOrderManager.calculatePlatformCommission(shopCartOrderMerger);

        // 缓存计算
        confirmOrderManager.cacheCalculatedInfo(userId, shopCartOrderMerger);
        return ServerResponseEntity.success(shopCartOrderMerger);
    }

    @PostMapping("/submit")
    @Operation(summary = "提交订单，返回订单编号" , description = "根据订单信息，返回订单编号")
    public ServerResponseEntity<OrderNumbersDto> submitOrders(@Valid @RequestBody ApiGroupOrderSubmitParam apiGroupOrderSubmitParam) {
        String userId = SecurityUtils.getUser().getUserId();
        ServerResponseEntity<ShopCartOrderMergerDto> orderCheckResult = submitOrderManager.checkSubmitInfo(apiGroupOrderSubmitParam, userId);
        if (!orderCheckResult.isSuccess()) {
            if (CharSequenceUtil.equals(ResponseEnum.REPEAT_ORDER.value(), orderCheckResult.getCode())) {
                OrderNumbersDto orderNumbersDto = new OrderNumbersDto(null);
                orderNumbersDto.setDuplicateError(1);
                return ServerResponseEntity.success(orderNumbersDto);
            }
        }
        ShopCartOrderMergerDto mergerOrder = orderCheckResult.getData();
        String orderNumber = String.valueOf(segmentService.getDateFormatSegmentId(SegmentIdKey.ORDER));
        if (Objects.isNull(mergerOrder.getUserAddr()) && !Objects.equals(mergerOrder.getMold(),1) && Objects.equals(mergerOrder.getDvyTypes().get(0).getDvyType(), DeliveryType.EXPRESS.getValue())) {
            // 请填写收货地址
            throw new YamiShopBindException("yami.delivery.address");
        }
        List<ShopCartOrderDto> shopCartOrders = mergerOrder.getShopCartOrders();
        ShopCartOrderDto shopCartOrderVO = shopCartOrders.get(0);
        shopCartOrderVO.setOrderNumber(orderNumber);
        ShopCartItemDto shopCartItemVO = shopCartOrderVO.getShopCartItemDiscounts().get(0).getShopCartItems().get(0);
        Long prodId = shopCartItemVO.getProdId();

        ApiGroupActivityDto apiGroupActivityDto = groupActivityService.getByProdId(prodId);
        // 校验活动
        checkGroupNum(userId, apiGroupActivityDto, shopCartItemVO, apiGroupOrderSubmitParam, prodId);

        GroupOrderBO groupOrderBO = new GroupOrderBO();
        groupOrderBO.setGroupTeamId(apiGroupOrderSubmitParam.getGroupTeamId());
        groupOrderBO.setGroupActivityId(apiGroupActivityDto.getGroupActivityId());
        groupOrderBO.setShopId(shopCartOrderVO.getShopId());
        groupOrderBO.setUserId(userId);
        groupOrderBO.setShareUserId(userId);
        groupOrderBO.setActivityProdPrice(mergerOrder.getTotal());
        groupOrderBO.setPayPrice(mergerOrder.getActualTotal());
        groupOrderBO.setOrderNumber(shopCartOrderVO.getOrderNumber());
        groupOrderBO.setCount(shopCartOrderVO.getTotalCount());
        groupOrderBO.setProdId(shopCartItemVO.getProdId());
        groupOrderService.submit(mergerOrder,groupOrderBO);
        // 店铺客户创建
        Order order = new Order();
        order.setUserId(groupOrderBO.getUserId());
        order.setShopId(groupOrderBO.getShopId());
        shopCustomerService.saveCustomerByOrders(Collections.singletonList(order));
        // 移除缓存
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartOrder.getShopCartItemDiscounts()) {
                for (ShopCartItemDto shopCartItem : shopCartItemDiscount.getShopCartItems()) {
                    skuService.removeSkuCacheBySkuId(shopCartItem.getSkuId(), shopCartItem.getProdId());
                    productService.removeProdCacheByProdId(shopCartItem.getProdId());
                }
            }
        }

        // 插入流量数据
        flowLogService.saveSubmitOrder(apiGroupOrderSubmitParam.getOrderFlowLogParam(), userId, String.valueOf(orderNumber));
        return ServerResponseEntity.success(new OrderNumbersDto(orderNumber));
    }

    private void checkGroupNum(String userId, ApiGroupActivityDto apiGroupActivityDto, ShopCartItemDto shopCartItemVO, ApiGroupOrderSubmitParam apiGroupOrderSubmitParam, Long prodId) {
        if (Objects.isNull(apiGroupActivityDto) || !Objects.equals(apiGroupActivityDto.getActivityStatus(), ActivityStatusEnum.UNDER_WAY.value())) {
            // 拼团活动不在进行中，不能参与拼团
            throw new YamiShopBindException("yami.group.no.progress");
        }
        if (Objects.equals(apiGroupActivityDto.getHasMaxNum(), 1)) {
            Integer dbSpuCount = groupOrderService.getUserHadOrderCountByGroupProdId(userId, apiGroupActivityDto.getGroupActivityId());
            if (dbSpuCount + shopCartItemVO.getProdCount() > apiGroupActivityDto.getMaxNum()) {
                String message = I18nMessage.getMessage("yami.group.prod.shop.limit");
                String num = I18nMessage.getMessage("yami.seckill.num");
                String userNum = I18nMessage.getMessage("yami.group.user.shop.num");
                String nowNum = I18nMessage.getMessage("yami.group.user.now.shop");
                String maxNum = I18nMessage.getMessage("yami.group.prod.overstep.shop.limit");
                // 活动商品限购数量为x件，您已购买x件，现购x件，超出最大得购买数量
                throw new YamiShopBindException(message + apiGroupActivityDto.getMaxNum() + num + userNum
                        + dbSpuCount + num + nowNum + shopCartItemVO.getProdCount() + num + maxNum);
            }
        }
        // 查看未完成的订单数量
        int unGroupOrderCount = groupOrderService.getUserUnGroupOrderCount(userId, apiGroupActivityDto.getGroupActivityId(), prodId);
        if (0 < unGroupOrderCount) {
            // 您已有待成团或拼团中的订单，请在拼团成功后重试
            throw new YamiShopBindException("yami.group.prod.has.group.order");
        }
        // 校验拼团团队是否可以参团
        if (Objects.nonNull(apiGroupOrderSubmitParam.getGroupTeamId()) && apiGroupOrderSubmitParam.getGroupTeamId() != 0) {
            GroupTeam groupTeam = groupTeamService.getById(apiGroupOrderSubmitParam.getGroupTeamId());
            if (!Objects.equals(TeamStatusEnum.IN_GROUP.value(), groupTeam.getStatus())) {
                // 拼团团队不在拼团中，不能参与拼团
                throw new YamiShopBindException("yami.group.team.no.join");
            }
            if (System.currentTimeMillis() > groupTeam.getEndTime().getTime()) {
                // 该拼团团队已关闭，不能继续参团
                throw new YamiShopBindException("yami.group.order.no.exist");
            }
        }
    }


    /**
     * 检查活动状态
     */
    private ApiGroupSkuDto checkActivityAndGetGroupSku(GroupOrderParam groupOrderParam) {
        Long prodId = groupOrderParam.getOrderItem().getProdId();
        ApiGroupActivityDto activityDto = groupActivityService.getByProdId(prodId);
        if (Objects.isNull(activityDto) || !Objects.equals(activityDto.getActivityStatus(), ActivityStatusEnum.UNDER_WAY.value()) || activityDto.getEndTime().getTime() < System.currentTimeMillis()) {
            // 拼团活动不在进行中，请稍后重试
            throw new YamiShopBindException("yami.group.no.progress");
        }
        ApiGroupSkuDto apiGroupSku = null;
        List<ApiGroupSkuDto> groupSkuList = activityDto.getGroupSkuList();
        for (ApiGroupSkuDto apiGroupSkuDto : groupSkuList) {
            if (Objects.equals(apiGroupSkuDto.getGroupSkuId(), groupOrderParam.getGroupSkuId())) {
                apiGroupSku = apiGroupSkuDto;
                break;
            }
        }
        if (Objects.isNull(apiGroupSku)) {
            // 活动商品不在正常状态
            throw new YamiShopBindException("yami.group.prod.status.error");
        }
        return apiGroupSku;
    }
}
